package com.oa.admin.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.joneying.common.annotation.CommonService;
import com.joneying.common.web.response.Resp;
import com.oa.admin.dto.LeaveApplyAddDTO;
import com.oa.admin.dto.LeaveApplyListDTO;
import com.oa.admin.entity.Holiday;
import com.oa.admin.entity.LeaveApply;
import com.oa.admin.entity.UserHoliday;
import com.oa.admin.mapper.LeaveApplyMapper;
import com.oa.admin.service.IHolidayService;
import com.oa.admin.service.ILeaveApplyService;
import com.oa.admin.service.IUserHolidayService;
import com.oa.admin.vo.LeaveApplyDetailsVO;
import com.oa.admin.vo.LeaveApplyListVO;
import com.oa.core.PageResult;
import com.oa.core.enumm.ProcessDefineEnum;
import com.oa.core.exception.BusinessException;
import com.oa.core.exception.DataIsEmptyException;
import com.oa.core.utils.DateUtil;
import com.oa.core.utils.ExcelUtil;
import com.oa.system.dto.ApplyApprovalAddDTO;
import com.oa.system.dto.ApprovalDTO;
import com.oa.system.entity.ApplyApproval;
import com.oa.system.entity.ProcessInfoSubmit;
import com.oa.system.entity.User;
import com.oa.system.service.IApplyApprovalService;
import com.oa.system.service.IProcessInfoSubmitService;
import com.oa.system.service.IUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.*;

@Service
public class LeaveApplyServiceImpl extends ServiceImpl<LeaveApplyMapper, LeaveApply> implements ILeaveApplyService {

    @Autowired
    private LeaveApplyMapper leaveApplyMapper;

    @Autowired
    private IUserService userService;

    @Autowired
    private IApplyApprovalService applyApprovalService;

    @Autowired
    private IUserHolidayService userHolidayService;

    @Autowired
    private IHolidayService holidayService;

    @Autowired
    private IProcessInfoSubmitService processInfoSubmitService;

    @Override
    public PageResult<LeaveApplyListVO> findLeaveApplyList(LeaveApplyListDTO leaveApplyListDTO) {
        Page page = leaveApplyListDTO.getPage();
        return new PageResult<>(leaveApplyMapper.findLeaveApplyList(page, leaveApplyListDTO), page);
    }

    @Override
    public LeaveApplyDetailsVO findLeaveApplyDetails(String id) {
        return leaveApplyMapper.findLeaveApplyDetails(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @CommonService
    @Override
    public Resp add(String userId, LeaveApplyAddDTO leaveApplyAddDTO) throws BusinessException, DataIsEmptyException {

        LeaveApply leaveApply = new LeaveApply();
        BeanUtils.copyProperties(leaveApplyAddDTO, leaveApply);
        leaveApply.setCreateTime(new Date());
        leaveApply.setStatus(1);
        leaveApply.setUserId(userId);


        Map<Long, ProcessInfoSubmit> processInfoSubmitMap = new HashMap<>();
        ProcessInfoSubmit processInfoSubmit = new ProcessInfoSubmit();
        processInfoSubmit.setAssemblyId(Long.valueOf(1));
        processInfoSubmit.setInitiatorId(userId);
        processInfoSubmit.setValue(String.valueOf(calculationDay(leaveApplyAddDTO.getLeaveStartTime(), leaveApplyAddDTO.getLeaveEndTime())));
        processInfoSubmit.setSubmitTime(new Date());
        processInfoSubmitMap.put(processInfoSubmit.getAssemblyId(), processInfoSubmit);

        if (insert(leaveApply)) {
            User user = userService.selectById(userId);

            ApplyApprovalAddDTO applyApprovalAddDTO = new ApplyApprovalAddDTO();
            applyApprovalAddDTO.setApplyId(leaveApply.getId());
            applyApprovalAddDTO.setApprovalProcessId(ProcessDefineEnum.LEAVE.getId());
            applyApprovalAddDTO.setApplyApprovalName(user.getName() + ProcessDefineEnum.LEAVE.getText());
            applyApprovalAddDTO.setApprovalUserId(user.getId());
            applyApprovalAddDTO.setApprovalPlanId(applyApprovalService.getPlanId(userId, processInfoSubmitMap, ProcessDefineEnum.LEAVE.getId()));
            return applyApprovalService.addApproval(applyApprovalAddDTO);
        }
        throw new BusinessException("提交申请失败!");
    }

    @Transactional(rollbackFor = Exception.class)
    @CommonService
    @Override
    public Resp audit(String id, String applyApprovalId, Integer status) throws DataIsEmptyException, BusinessException {
        ApprovalDTO approvalDTO = new ApprovalDTO();
        approvalDTO.setId(Long.valueOf(applyApprovalId));
        approvalDTO.setUserId("1");
        approvalDTO.setStatus(status);
        return applyApprovalService.audit(approvalDTO, d -> {
            if(d.getStatus() == 1){
                return;
            }
            if(!d.isLastStatus()){
                return;
            }

            Calendar calendar = Calendar.getInstance();

            LeaveApply leaveApply = leaveApplyMapper.selectById(id);
            leaveApply.setStatus(2);

            Date leaveStartTime = leaveApply.getLeaveStartTime();
            Date leaveEndTime = leaveApply.getLeaveEndTime();


            Holiday holiday = holidayService.selectById(leaveApply.getLeaveType());
            if(holiday.getHolidayType() == 2 && holiday.getHolidayNumber() > 0){

                UserHoliday userHoliday = userHolidayService.selectOne(new EntityWrapper().eq("user_id", leaveApply.getUserId()).eq("holiday_id", leaveApply.getLeaveType()));
                userHoliday.setAlreadyUsedDay(userHoliday.getAlreadyUsedDay() == null ? 0 : userHoliday.getAlreadyUsedDay() + calculationDay(leaveStartTime, leaveEndTime));
                if (userHoliday.getSurplusDay() > 0) {
                    userHoliday.setSurplusDay(userHoliday.getSurplusDay() - calculationDay(leaveStartTime, leaveEndTime));
                }
                userHolidayService.updateById(userHoliday);

            }
            updateById(leaveApply);
        });
    }

    @Override
    public Double calculationDay(Date beginTime, Date endTime){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(beginTime);
        Integer startDay = calendar.get(Calendar.DAY_OF_YEAR);
        Integer startHour = calendar.get(Calendar.HOUR_OF_DAY);

        calendar.setTime(endTime);
        Integer endDay = calendar.get(Calendar.DAY_OF_YEAR);
        Integer endHour = calendar.get(Calendar.HOUR_OF_DAY);

        double resultDay = 0.0;

        double day, hour;

        day = endDay - startDay;

        if(day > 0.0){
            if(endHour >= startHour){
                hour = endHour - startHour;
            }else{
                hour = startHour - endHour;
            }

            if(hour == 9.0){
                resultDay += 1.0;
            }else{
                resultDay += hour / 10.0;
            }
        }
        resultDay += day;
        return resultDay;
    }

    @Override
    public void export(LeaveApplyListDTO leaveApplyListDTO, HttpServletResponse response) {
        List<LeaveApplyListVO> leaveApplyList = leaveApplyMapper.findLeaveApplyList(leaveApplyListDTO.getPage() == null? new Page() : leaveApplyListDTO.getPage(), leaveApplyListDTO);

        String[] rows = {"编号", "姓名", "部门", "请假类别", "申请时间", "开始时间", "结束时间", "审批状态"};

        try {
            ExcelUtil.downloadExcel("请假申请列表" + DateUtil.getDayMonth(), rows, leaveApplyList, "请假申请列表" + DateUtil.getDayMonth()+".xls", response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
